package ru.ifmo.rybakov.muclumon;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

public class PropertyManager {

	private static final PropertyManager instance = new PropertyManager();
	
	public static PropertyManager getInstance() {
		return instance;
	}
	
	private Map<String, Property> properties;
	
	@SuppressWarnings("unchecked")
	private void loadProperties() {
		properties = new HashMap<String, Property>();
		EntityManager em = Database.getEntityManagerFactory().createEntityManager();
		try {
			List<Property> propertiesFromDB = em.createQuery("SELECT p FROM Property p").getResultList();
			Iterator<Property> it = propertiesFromDB.iterator();
			while (it.hasNext()) {
				Property p = it.next();
				properties.put(p.getName(), p);
			}
		} finally {
			em.close();
		}
	}
	
	public static Property get(String name) {
		return getInstance().getProperty(name);
	}
	
	public synchronized Property getProperty(String name) {
		if (properties == null) {
			 loadProperties();
		}
		Property p = properties.get(name);
		if (p == null) {
			p = createProperty(name);
			properties.put(name, p);
		}
		return p;
	}
	
	private Property createProperty(String name) {
		Property p = new Property(name);
		EntityManager em = Database.getEntityManagerFactory().createEntityManager();
		try {
			EntityTransaction t = em.getTransaction();
			try {
				t.begin();
				em.persist(p);
				t.commit();
			} finally {
				if (t.isActive()) t.rollback();
			}
		} finally {
			em.close();
		}
		return p;
	}
	
//	public void bind(Property property) {
//		synchronized (properties) {
//			assert(property.getId() != null);
//			assert(!properties.containsKey(property.getId()));
//			properties.put(property.getId(), property);
//			
//			// now merge property
//			EntityManager em = Database.getEntityManagerFactory().createEntityManager();
//			try {
//				if (em.find(Property.class, property.getId()) == null) {
//					EntityTransaction t = em.getTransaction();
//					try {
//						t.begin();
//						em.persist(property);
//						t.commit();
//					} finally {
//						if (t.isActive()) t.rollback();
//					}
//				}
//			} finally {
//				em.close();
//			}
//		}
//	}
}
